import { TreeListRTBase } from "./TreeListRT.generated";

const { regClass, property } = Laya;

/**
 * @author Charley
 * 树状列表的多层级数据示例
 */
@regClass()
export default class TreeListRT extends TreeListRTBase {

    onEnable(): void {
        // 给 tree 设置 XML 数据源 —— 一份静态示例（多层），一份程序生成（多层）
        this.tree1.xml = this.getTreeData(true);
        this.tree2.xml = this.getTreeData(false);
    }

    /**
     * 生成演示用树形 XML（支持任意层级）
     * @param isStatic 如果为 true 返回静态对象生成的 XML；为 false 则程序递归生成多层结构
     */
    getTreeData(isStatic: boolean): any {
        const parts: string[] = [];
        parts.push("<data>");

        if (isStatic) {
            // 静态示例：对象结构，便于维护
            const demoRoots = [
                {
                    label: "一级目录",
                    isOpen: false,
                    children: [
                        { label: "二级子项" },
                        { label: "二级子项" },
                        { label: "二级子项" }
                    ]
                },
                {
                    label: "一级目录",
                    isOpen: true,
                    children: [
                        {
                            label: "二级目录",
                            isOpen: true,
                            children: [
                                { label: "三级子项" },
                                { label: "三级子项" }
                            ]
                        },
                        { label: "二级子项" }
                    ]
                },
                { label: "一级子项", isFile: true }
            ];

            const buildXml = (node: any, indexPath: number[]): void => {
                const num = indexPath.join(".");
                const display = `${num} ${node.label ?? ""}`; // 只在前面加序号

                if (node.isFile) {
                    parts.push(`<file itemLabel='${this._esc(display)}' label='${this._esc(display)}' title='${this._esc(display)}' isDirectory='false'/>`);
                } else if (node.children && node.children.length > 0) {
                    const isOpenAttr = node.isOpen ? "true" : "false";
                    parts.push(`<dir itemLabel='${this._esc(display)}' label='${this._esc(display)}' title='${this._esc(display)}' isOpen='${isOpenAttr}'>`);
                    for (let i = 0; i < node.children.length; i++) {
                        buildXml(node.children[i], indexPath.concat(i + 1));
                    }
                    parts.push(`</dir>`);
                } else {
                    parts.push(`<file itemLabel='${this._esc(display)}' label='${this._esc(display)}' title='${this._esc(display)}' isDirectory='false'/>`);
                }
            };

            for (let i = 0; i < demoRoots.length; i++) {
                buildXml(demoRoots[i], [i + 1]);
            }

        } else {
            const maxDepth = 4;
            const branches = 3;

            const makeNode = (depth: number, indexPath: number[]): void => {
                const num = indexPath.join(".");

                if (depth >= maxDepth) {
                    const display = `${num} File`;
                    parts.push(`<file itemLabel='${this._esc(display)}' label='${this._esc(display)}' title='${this._esc(display)}' isDirectory='false'/>`);
                    return;
                }

                const display = `${num} Dir`;
                const isOpen = depth < 2 ? "true" : "false";
                parts.push(`<dir itemLabel='${this._esc(display)}' label='${this._esc(display)}' title='${this._esc(display)}' isOpen='${isOpen}'>`);

                for (let i = 1; i <= branches; i++) {
                    makeNode(depth + 1, indexPath.concat(i));
                }

                parts.push(`</dir>`);
            };

            for (let r = 1; r <= 2; r++) {
                makeNode(0, [r]);
            }
        }

        parts.push("</data>");
        return new Laya.XML(parts.join(""));
    }

    private _esc(s: string): string {
        if (s == null) return "";
        return String(s)
            .replace(/&/g, "&amp;")
            .replace(/'/g, "&apos;")
            .replace(/"/g, "&quot;")
            .replace(/</g, "&lt;")
            .replace(/>/g, "&gt;");
    }
}
